package com.itc.bi.handler.dataSet;

import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itc.bi.constant.DataDirectorConstant;
import com.itc.bi.constant.SystemConstant;
import com.itc.bi.dto.DataSetCreateDto;
import com.itc.bi.entity.*;
import com.itc.bi.handler.DatasourceHandler;
import com.itc.bi.service.*;
import com.itc.common.core.exception.CheckedException;
import com.itc.common.core.exception.ServiceException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class Database extends DataSet {

    @Autowired
    DirectDataSetService dataSetService;
    @Autowired
    DatasourceService datasourceService;
    @Autowired
    TableService tableService;
    @Autowired
    private DirectoryService directoryService;
    @Autowired
    DataSetColumnService dataSetColumnService;
    @Autowired
    TableColumnService tableColumnService;

    public void create(DataSetCreateDto dto){
        Assert.hasText(dto.getType(),"数据集类型不能为空");
        Assert.notNull(dto.getDtId(),"目录不能为空");
        Assert.notNull(dto.getDsId(),"数据源不能为空");
        Assert.notEmpty(dto.getTables(),"表集合不能为空");
        List<String> l=dto.getTables().stream().distinct().collect(Collectors.toList());
        if(dto.getTables().size() != l.size()){
            throw new CheckedException("表重复，请检查");
        }
        //验证同目录下同数据源表是否已经创建数据集
        LambdaQueryWrapper<DirectDataSetEntity> qw = Wrappers.lambdaQuery();
        qw.eq(DirectDataSetEntity::getDtId,dto.getDtId());
        qw.eq(DirectDataSetEntity::getDsId,dto.getDsId());
        qw.in(DirectDataSetEntity::getTableName,dto.getTables());
        List<DirectDataSetEntity> list = dataSetService.list(qw);
        if(null != list && list.size()>0){
            List<String> tables= list.stream().map(DirectDataSetEntity::getTableName).collect(Collectors.toList());
            throw new CheckedException(tables.toString()+"已经存在数据集");
        }
        //判断表是否存在
        LambdaQueryWrapper<TableEntity> tableQw = Wrappers.lambdaQuery();
        tableQw.eq(TableEntity::getDatasourceId,dto.getDsId());
        tableQw.in(TableEntity::getTableName,dto.getTables());
        List<TableEntity> tableList = tableService.list(tableQw);
        if(dto.getTables().size() != tableList.size()){
            List<String> tables = dto.getTables();
            tableList.stream().forEach(item->{
                if(tables.contains(item.getTableName())){
                    tables.remove(item.getTableName());
                }
            });
            throw new CheckedException("数据库中不存在表:"+tables.toString());
        }
        List<DirectDataSetEntity> setList = new ArrayList<>();
        List<DirectoryEntity> dirList = new ArrayList<>();

        dto.getTables().stream().forEach(tableName -> {
            DirectDataSetEntity entity = new DirectDataSetEntity();
            entity.setId(IdWorker.getId());
            entity.setDtId(dto.getDtId());
            entity.setDsId(dto.getDsId());
            entity.setTableName(tableName);
            entity.setType(dto.getType());
            setList.add(entity);

            long count = directoryService.count((Wrappers.<DirectoryEntity>lambdaQuery().eq(DirectoryEntity::getPid, dto.getDtId()).likeRight(DirectoryEntity::getName, tableName)));
            if(count>0) {
                tableName = tableName+count;
            }
            DirectoryEntity dir = new DirectoryEntity();
            dir.setDtId(entity.getId());
            dir.setPid(dto.getDtId());
            dir.setName(tableName);
            dir.setIsDir(DataDirectorConstant.ISDATASET);
            dirList.add(dir);
            List<DataSetColumnEntity> cloumnList = column(entity);
            dataSetColumnService.saveBatch(cloumnList);
        });
        dataSetService.saveBatch(setList);
        directoryService.saveBatch(dirList);
    }

    @Override
    public List<Object> previewData(DirectDataSetEntity dataSet,Integer pageIndex,Integer pageSize){
        DatasourceEntity datasource = getDadasource(dataSet.getDsId());
        DatasourceHandler handler = DatasourceHandler.datasourceFactory(datasource);
        IPage page = handler.getPageDataBySql(DatasourceHandler.getSqlBytableName(dataSet.getTableName()),1,SystemConstant.DATA_COLLECT_PREVIEW_SIZE,null);
        handler.closeConn();
        return page.getRecords();
    }

    @Override
    public List<Object> list(DirectDataSetEntity dataSet){
        DatasourceEntity datasource = getDadasource(dataSet.getDsId());
        DatasourceHandler handler = DatasourceHandler.datasourceFactory(datasource);
        JSONArray arr = handler.getDataBySql(DatasourceHandler.getSqlBytableName(dataSet.getTableName()));
        handler.closeConn();
        return arr;
    }

    @Override
    public IPage page(DirectDataSetEntity dataSet,Integer pageIndex,Integer pageSize){
        DatasourceEntity datasource = getDadasource(dataSet.getDsId());
        DatasourceHandler handler = DatasourceHandler.datasourceFactory(datasource);
        IPage page = handler.getPageDataBySql(DatasourceHandler.getSqlBytableName(dataSet.getTableName()),pageIndex,pageSize,null);
        handler.closeConn();
        return page;
    }

    @Override
    public List<DataSetColumnEntity> column(DirectDataSetEntity dataSet){

        LambdaQueryWrapper<TableEntity> tableQw = Wrappers.lambdaQuery();
        tableQw.eq(TableEntity::getDatasourceId,dataSet.getDsId());
        //tableQw.eq(TableEntity::getTableName,dataSet.getTableName());
        List<TableEntity> tableList = tableService.list(tableQw);
        TableEntity tableEntity = tableList.stream().filter(item -> item.getTableName().equalsIgnoreCase(dataSet.getTableName())).findFirst().orElse(null);
        if(null == tableEntity){
            throw new ServiceException("表不存在");
        }

        //查询tb_table_column表数据
        LambdaQueryWrapper<TableColumnEntity> columnQw = Wrappers.lambdaQuery();
        columnQw.eq(TableColumnEntity::getTableId,tableEntity.getId());
        List<TableColumnEntity> tableColumnList = tableColumnService.list(columnQw);

        //获取数据类型
        DatasourceEntity datasource = getDadasource(dataSet.getDsId());
        String sql = "select * from "+ dataSet.getTableName()+" where 1=2";
        DatasourceHandler handler = DatasourceHandler.datasourceFactory(datasource);
        List<DataSetColumnEntity> list = handler.getSqlColumn(sql,null);
        handler.closeConn();
        Map<String, String> nameToCommentMap = list.stream().collect(Collectors.toMap(DataSetColumnEntity::getColumnName, DataSetColumnEntity::getColumnType));

        Long dtId = dataSet.getId();
        List<DataSetColumnEntity> columnList = new ArrayList<>();
        for (TableColumnEntity tableColumn : tableColumnList){
            DataSetColumnEntity column = new DataSetColumnEntity();
            column.setDataSetId(dtId);
            column.setColumnName(tableColumn.getColumnName());
            column.setColumnComment(StringUtils.isNoneBlank(tableColumn.getColumnComment())?tableColumn.getColumnComment():column.getColumnName());
            column.setColumnType(nameToCommentMap.getOrDefault(tableColumn.getColumnName(),SystemConstant.DATA_TYPE_STRING));
            column.setColumnPosition(tableColumn.getColumnPosition());
            columnList.add(column);
        }

        return columnList;
    }

    private DatasourceEntity getDadasource(Long id){
        DatasourceEntity datasource = datasourceService.getDecodeData(id);
        if(null == datasource){
            throw new ServiceException("数据源不存在");
        }
        return datasource;
    }
}
